package cn.stylefeng.guns.modular.shuheng.controller;

import cn.stylefeng.guns.config.properties.GunsProperties;
import cn.stylefeng.guns.core.common.annotion.Permission;
import cn.stylefeng.guns.core.common.constant.Constants;
import cn.stylefeng.guns.core.common.exception.ApiExceptionEnum;
import cn.stylefeng.guns.core.common.exception.BizExceptionEnum;
import cn.stylefeng.guns.core.common.node.ZTreeNode;
import cn.stylefeng.guns.core.common.page.LayuiPageFactory;
import cn.stylefeng.guns.core.shiro.ShiroKit;
import cn.stylefeng.guns.core.shiro.ShiroUser;
import cn.stylefeng.guns.core.util.DateUtil;
import cn.stylefeng.guns.core.util.FileUtil;
import cn.stylefeng.guns.core.util.UUIDUtil;
import cn.stylefeng.guns.modular.shuheng.entity.Content;
import cn.stylefeng.guns.modular.shuheng.entity.Data;
import cn.stylefeng.guns.modular.shuheng.entity.Files;
import cn.stylefeng.guns.modular.shuheng.entity.Level;
import cn.stylefeng.guns.modular.shuheng.service.ContentService;
import cn.stylefeng.guns.modular.shuheng.service.DataService;
import cn.stylefeng.guns.modular.shuheng.service.FilesService;
import cn.stylefeng.guns.modular.shuheng.service.LevelService;
import cn.stylefeng.guns.modular.shuheng.warpper.DataWrapper;
import cn.stylefeng.roses.core.base.controller.BaseController;
import cn.stylefeng.roses.core.reqres.response.ResponseData;
import cn.stylefeng.roses.core.util.ToolUtil;
import cn.stylefeng.roses.kernel.model.exception.RequestEmptyException;
import cn.stylefeng.roses.kernel.model.exception.ServiceException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.io.IOUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

@Controller
@RequestMapping("/deal")
public class DealController extends BaseController {
    private String PREFIX = "/modular/shuheng/deal/";

    @Autowired
    private LevelService levelService;

    @Autowired
    private ContentService contentService;

    @Autowired
    private DataService dataService;

    @Autowired
    private FilesService filesService;

    @Autowired
    private GunsProperties gunsProperties;

    @RequestMapping("")
    public String index(@RequestParam(value = "year",required = false) Integer year,
                        @RequestParam(value = "month",required = false) Integer month,Model model){
        Calendar calendar = Calendar.getInstance();
        Integer nowYear = calendar.get(Calendar.YEAR);
        List<Integer> list = new ArrayList<>();
        list.add(nowYear);
        list.add(nowYear +1);
        list.add(nowYear +2);
        model.addAttribute("yearList",list);
        if(ToolUtil.isEmpty(year)){
            year = nowYear;
        }
        return PREFIX + "deal.html";
    }

    @RequestMapping(value = "/list")
    @ResponseBody
    public Object list(@RequestParam(value = "condition", required = false) String condition,
                       @RequestParam(value = "parentId", required = false) Long parentId,
                       @RequestParam(value = "year",required = false) Integer year) {
        ShiroUser user = ShiroKit.getUser();
        Calendar calendar = Calendar.getInstance();
        Integer nowYear = calendar.get(Calendar.YEAR);
        if(year==null){
            year = nowYear;
        }
        //根据不同的用户层级，年度，上级id来查询任务
        Page<Map<String, Object>> list = this.dataService.list(condition, parentId,year,user.getUserLevel(),user.getProvince(),user.getCity(),user.getCounty());
        Page<Map<String, Object>> wrap = new DataWrapper(list).wrap();
        return LayuiPageFactory.createPageInfo(wrap);
    }



    @RequestMapping(value = "/tree")
    @ResponseBody
    public List<ZTreeNode> tree(@RequestParam(value = "year",required = false) Integer year) {
        ShiroUser user = ShiroKit.getUser();
        Calendar calendar = Calendar.getInstance();
        Integer nowYear = calendar.get(Calendar.YEAR);
        Integer nowMonth = calendar.get(Calendar.MONTH) + 1;
        List<ZTreeNode> tree = this.levelService.tree(year,user.getUserLevel());
        if(tree!=null && tree.size()>0){
            for(int i=0;i<tree.size();i++){
                if("level".equals(tree.get(i).getType())){
                    boolean flag = levelService.exitNotDeal(nowYear,nowMonth,tree.get(i).getId(),user);
                    tree.get(i).setColor(flag);
                }
                if("content".equals(tree.get(i).getType())){
                    boolean flag = contentService.exitNotDeal(nowYear,nowMonth,tree.get(i).getId(),user);
                    tree.get(i).setColor(flag);
                }
            }
        }
        tree.add(ZTreeNode.createParent());
        return tree;
    }


    /**
     * 跳转导入页面
     * @return
     */
    @RequestMapping("/toImport")
    public String toImport(){
        return PREFIX + "import.html";
    }

    /**
     * 导入任务
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping("/import")
    @ResponseBody
    @Transactional
    public Map import_(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String path = (String) request.getParameter("path");
        if(ToolUtil.isEmpty(path)){
            path = Constants.ZIP_PATH;
        }else{
            path = Constants.UPLOAD_PATH + path + File.separator;
        }
        Map data = new HashMap();
        data.put("code",0);
        data.put("msg","导入完成");
        // 视频路径
        String filePath = "";
        // 视频名称
        String orgFileName = null;
        // 视频后缀
        String fileExt = null;
        // 文件格式错误信息
        String fileExtError = null;
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();

        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            // 上传文件
            MultipartFile mf = entity.getValue();
            // 获取文件大小
            long picSize = mf.getSize();
            // 获取原文件名
            String fileName =  mf.getOriginalFilename();
            // 获取图片后缀
            fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
            if (!Constants.ZIP.equals(fileExt)) {
                fileExtError = "请上传zip格式文件";
                data.put("code","1");
                data.put("msg",fileExtError);
                return data;
            } else if (picSize > Constants.ONE_HUNDRED_MB) {
                fileExtError = "文件最大100M";
                data.put("code","2");
                data.put("msg",fileExtError);
                return data;
            } else {
                // 对原文件名进行重命名
                fileName = UUIDUtil.uuid() + "." + fileExt;
                // 返回文件路径
                String rootPath = FileUtil.getRootPath(request,gunsProperties.getJarName());
                filePath = path + fileName;
                File dic = new File(rootPath + path);
                if(!dic.exists()){
                    dic.mkdirs();
                }
                //上传至服务器
                String realPath = rootPath + filePath;
                mf.transferTo(new File(realPath));

                //上传成功后读取zip
                ZipFile zipFile = new ZipFile(realPath);
                InputStream in = new BufferedInputStream(new FileInputStream(realPath));
                ZipInputStream zin = new ZipInputStream(in);
                ZipEntry ze;
                StringBuffer json = new StringBuffer();
                while((ze = zin.getNextEntry()) != null){
                    if(ze.toString().endsWith("json")){
                        BufferedReader br = new BufferedReader(
                                new InputStreamReader(zipFile.getInputStream(ze),"UTF-8"));
                        String line;
                        while((line = br.readLine()) != null){
                            json.append(line);
                        }
                        br.close();
                    }
                }
                zin.close();
                in.close();

                JSONObject jsonObject = JSON.parseObject(json.toString());
                JSONArray levelArr = jsonObject.getJSONArray("levelList");
                JSONArray contentArr = jsonObject.getJSONArray("contentList");
                JSONArray dataArr = jsonObject.getJSONArray("dataList");
                List<Level> levelList = new ArrayList<>();
                List<Content> contentList = new ArrayList<>();
                List<Data> dataList = new ArrayList<>();
                Integer year = 0;
                for(int i=0;i<levelArr.size();i++){
                    Level level = JSON.toJavaObject(levelArr.getJSONObject(i),Level.class);
                    levelList.add(level);
                    if(i==0){
                        year = level.getYear();
                    }
                }
                for(int i=0;i<contentArr.size();i++){
                    Content content = JSON.toJavaObject(contentArr.getJSONObject(i),Content.class);
                    contentList.add(content);
                }
                for(int i=0;i<dataArr.size();i++){
                    Data d = JSON.toJavaObject(dataArr.getJSONObject(i),Data.class);
                    dataList.add(d);
                }
                //删除要导入的年份的任务，再根据json转化的保存
                levelService.deleteByYear(year);
                levelService.saveBatch(levelList);
                contentService.deleteByYear(year);
                contentService.saveBatch(contentList);
                dataService.deleteByYear(year);
                dataService.saveBatch(dataList);

                return data;
            }
        }
        return data;
    }

    @RequestMapping("/toUpload")
    public String toUpload(@Param("dataId") String dataId, Model model){
        ShiroUser user = ShiroKit.getUser();
        if(ToolUtil.isEmpty(dataId)){
            throw new RequestEmptyException();
        }
        Data data = dataService.getById(dataId);
        model.addAttribute("data",data);
        Files exitFiles = filesService.getFilesByDataIdAndUser(data.getDataId(),user);
        model.addAttribute("files",exitFiles);
        return PREFIX + "upload.html";
    }

    @RequestMapping("/upload")
    @ResponseBody
    @Transactional
    public Map upload(HttpServletRequest request, HttpServletResponse response,@Param("dataId")Long dataId) throws IOException {
        ShiroUser user = ShiroKit.getUser();
        if(ToolUtil.isEmpty(dataId)){
            throw new RequestEmptyException();
        }
        Map resule = new HashMap() ;
        resule.put("code",0);
        resule.put("msg","上传成功");
        Data data = dataService.getById(dataId);

        String rootPath = FileUtil.getRootPath(request,gunsProperties.getJarName());
        Files exitFiles = filesService.findByDataId(data.getDataId(),user);
        if(exitFiles!=null){
            File exitFile = new File(rootPath + exitFiles.getFilePath());
            if(exitFile.exists()){
                exitFile.delete();
            }
            filesService.removeById(exitFiles.getFileId());
        }

        // 文件路径
        String filePath = "";
        // 文件名称
        String orgFileName = null;
        // 文件后缀
        String fileExt = null;
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();

        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            // 上传文件
            MultipartFile mf = entity.getValue();
            // 获取图片大小
            int fileSize = Integer.parseInt(String.valueOf(mf.getSize()));
            // 获取原文件名
            orgFileName = mf.getOriginalFilename();
            String fileName =  mf.getOriginalFilename();
            // 获取图片后缀
            fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
            if(Constants.EXCEL.equals(data.getDataType())){
                if(!Constants.XLS.equals(fileExt) && !Constants.XLSX.equals(fileExt)){
                    resule.put("code","1");
                    resule.put("msg","请上传excel文件");
                    return resule;
                }
            }
            if(Constants.WORD.equals(data.getDataType())){
                if(!Constants.DOC.equals(fileExt) && !Constants.DOCX.equals(fileExt)){
                    resule.put("code","1");
                    resule.put("msg","请上传word文件");
                    return resule;
                }
            }
            if(Constants.PDF.equals(data.getDataType())){
                if(!Constants.PDF.equals(fileExt)){
                    resule.put("code","1");
                    resule.put("msg","请上传PDF文件");
                    return resule;
                }
            }
            if(Constants.IMG.equals(data.getDataType())){
                if(!Constants.JPG.equals(fileExt) && !Constants.JPEG.equals(fileExt) && !Constants.PNG.equals(fileExt) && !Constants.GIF.equals(fileExt)
                        && !Constants.BMP.equals(fileExt)){
                    resule.put("code","1");
                    resule.put("msg","请上传JPG或PNG类型的图片文件");
                    return resule;
                }
            }
            if (fileSize > Constants.ONE_HUNDRED_MB) {
                resule.put("code","2");
                resule.put("msg","限制最大上传文件为100M");
                return resule;
            }
            // 对原文件名进行重命名
            fileName = UUIDUtil.uuid() + "." + fileExt;
            //用upload/年份做基本路径
            filePath = Constants.UPLOAD_PATH + data.getDataYear() + File.separator + fileName;
            File dic = new File(rootPath + Constants.UPLOAD_PATH + data.getDataYear());
            if(!dic.exists()){
                dic.mkdirs();
            }
            //上传至服务器
            String realPath = rootPath + filePath;
            mf.transferTo(new File(realPath));
            //保存files表
            Files files = new Files();
            files.setDataId(data.getDataId());
            files.setFileName(orgFileName);
            files.setFilePath(filePath);
            files.setFileType(fileExt);
            files.setRegionLevel(user.getUserLevel());
            files.setYear(data.getDataYear());
            files.setProvince(user.getProvince());
            files.setCity(user.getCity());
            files.setCounty(user.getCounty());
            if(DateUtil.getNowMonth()>data.getDataMonth()){
                //超期上传
                files.setStatus(1);
            }
            filesService.save(files);
            resule.put("file_type",fileExt);
            resule.put("file_name",orgFileName);
            resule.put("file_path",filePath.replace("\\","/"));
            return resule;
        }
        return resule;
    }

    @RequestMapping("/toExport")
    public String toExport(Model model){
        Calendar calendar = Calendar.getInstance();
        Integer nowYear = calendar.get(Calendar.YEAR);
        List<Integer> list = new ArrayList<>();
        list.add(nowYear);
        list.add(nowYear +1);
        list.add(nowYear +2);
        model.addAttribute("yearList",list);
        return PREFIX + "export.html";
    }


    /**
     * 导出已完成任务
     * 市导出市以及区县的
     * 区县只导出自己的
     * @param year
     * @param request
     * @param response
     */
    @RequestMapping("/export")
    @ResponseBody
    public ResponseData export(@RequestParam Integer year,
                       @RequestParam String months,
                       HttpServletRequest request, HttpServletResponse response){
        ShiroUser user = ShiroKit.getUser();
        if(ToolUtil.isEmpty(year)){
            throw new ServiceException(BizExceptionEnum.REQUEST_NULL);
        }

        try {
//            OutputStream out = response.getOutputStream();
//            response.setCharacterEncoding("UTF-8");
            String path = createZip(year,months,request);

//            byte[] data = getStream(path);
            // 压缩包名称
//            response.setHeader("Content-Disposition",
//                    "attachment;filename=" + URLEncoder.encode(year + "上报民兵工作完成情况("+user.getName()+").zip", "utf-8"));
//            response.addHeader("Content-Length", "" + data.length);
//            response.setContentType("application/octet-stream;charset=UTF-8");
//            IOUtils.write(data, out);
//            out.close();
        } catch (IOException e) {
            throw new ServiceException(BizExceptionEnum.SERVER_ERROR);
        }
        return SUCCESS_TIP;
    }

    /**
     * 删除已上传的资料
     * @param fileId
     * @return
     */
    @RequestMapping(value = "/deleteFile")
    @ResponseBody
    public ResponseData deleteFile(@RequestParam Long fileId,HttpServletRequest request) {
        if (ToolUtil.isEmpty(fileId)) {
            throw new ServiceException(BizExceptionEnum.REQUEST_NULL);
        }

        Files files = this.filesService.getById(fileId);
        if(files!=null){
            String rootPath = FileUtil.getRootPath(request,gunsProperties.getJarName());
            String filePath = rootPath +  files.getFilePath();
            File file = new File(filePath);
            if(file.exists()){
                file.delete();
            }
            this.filesService.removeById(fileId);
        }

        return SUCCESS_TIP;
    }

    private byte[] getStream(String filePath) {
        byte[] buffer = null;
        File file = new File(filePath);
        FileInputStream fis = null;
        ByteArrayOutputStream bos = null;
        try {
            bos = new ByteArrayOutputStream();
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            buffer = bos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(fis!=null)
                    fis.close();
                if(bos!=null)
                    bos.close();
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
        return buffer;
    }

    private String createZip(Integer year,String months,HttpServletRequest request) throws IOException {
        //查询完成的任务
        ShiroUser user = ShiroKit.getUser();
        String[] monthArr = months.split(",");
        List<Files> listFiles = filesService.listByUser(user,year,monthArr);
        if(listFiles==null || listFiles.size()==0){
            throw new ServiceException(BizExceptionEnum.FILES_NOT_EXIT);
        }

        Map<String,Object> map = new HashMap<>();
        map.put("listFiles",listFiles);
        String json = JSONObject.toJSONString(map);
        String rootPath = FileUtil.getRootPath(request,gunsProperties.getJarName());
        String filePath = Constants.FILES_PATH + year + File.separator ;
        File dir = new File(rootPath+filePath);
        if(!dir.exists()){
            dir.mkdirs();
        }else{
            FileUtil.deleteDir(rootPath+filePath);//删除files/year下的文件及目录，不包含year
        }
        File jsonFile = new File(rootPath + filePath + Constants.FILES_JSON);
        if(!jsonFile.exists()){
            jsonFile.createNewFile();
        }
        FileOutputStream outputStream = new FileOutputStream(jsonFile);
        outputStream.write(json.getBytes());
        outputStream.close();

        //json生成后复制上传的文件
        for(int i=0;i<listFiles.size();i++){
            File file = new File(rootPath+listFiles.get(i).getFilePath());
            if(file.exists()){
                FileUtil.copyFile(file,rootPath + filePath);
            }
        }

        String zipPath = rootPath + Constants.FILES_PATH + "files.zip";
        FileUtil.compressionFile(rootPath + filePath ,zipPath);

        return zipPath;
    }
}
